package com.yunshipei.core.ui.client;

import android.content.Context;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

import com.yunshipei.core.common.ContentValues;
import com.yunshipei.core.manager.XCloud2Map;
import com.yunshipei.core.model.DeveloperAppModel;
import com.yunshipei.core.model.InjectModel;
import com.yunshipei.core.model.InterceptModel;
import com.yunshipei.core.model.MatcherResult;
import com.yunshipei.core.model.OverrideRegexModel;
import com.yunshipei.core.model.XCloudAppModel;
import com.yunshipei.core.net.EnterClient;
import com.yunshipei.core.ui.view.EnterWebView;
import com.yunshipei.core.utils.FileUtils;
import com.yunshipei.core.utils.MimeTypeUtils;
import com.yunshipei.core.utils.YspLogUtils;

import org.xwalk.core.XWalkView;
import org.xwalk.core.XWalkWebResourceRequest;
import org.xwalk.core.XWalkWebResourceResponse;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public final class AdapterEnterWebViewClient extends EnterWebViewClient {

    private String mHomeURL = "";
    private MatcherResult mMatcherResult;
    private XCloud2Map xCloud2Map;

    //该对象仅用于enterplorer协议时，使用开发者模式的情况
    private DeveloperAppModel mDeveloperAppModel;

    private AdapterEnterWebViewClient(XWalkView view, OnEnterWebViewClientInteractionListener baseWebViewClientInteractionListener) {
        super(view, baseWebViewClientInteractionListener);
    }

    public AdapterEnterWebViewClient(EnterWebView app, String homeURl, MatcherResult matcherResult, OnEnterWebViewClientInteractionListener onEnterWebViewClientInteractionListener) {
        this(app, onEnterWebViewClientInteractionListener);
        this.mHomeURL = homeURl;
        this.mMatcherResult = matcherResult;
        this.xCloud2Map = XCloud2Map.getInstance();
    }

    @Override
    public boolean shouldOverrideUrlLoading(final XWalkView view, String url) {

        if (mEnterWebViewClientInteractionListener != null) {
            if (mEnterWebViewClientInteractionListener.shouldLoadUrlSelf(view, url)) {
                return true;
            }

            mEnterWebViewClientInteractionListener.onWebViewUrlChanged(url);

            final Uri uri = Uri.parse(url);
            if (uri == null) {
                view.loadUrl(url);
                return false;
            }

            //======开始匹配正则表达式======
            //正则匹配的前提是，只有在tab的URL是manifest中的startUrl的时候才可以匹配
            if (mMatcherResult == null && mEnterWebViewClientInteractionListener.matchOverrideUrl(url)) {
                return true;
            }
        }
        view.loadUrl(url);
        return false;
    }

    @Override
    public XWalkWebResourceResponse shouldInterceptLoadRequest(XWalkView view, XWalkWebResourceRequest request) {
        String url = request.getUrl().toString();
        Log.i("_shouldIntercept", url);
        Uri uri = Uri.parse(url);
        if (uri == null) {
            return null;
        }
        String encodePath = uri.getEncodedPath();
        if (TextUtils.isEmpty(encodePath)) {
            return null;
        }

        String type = MimeTypeUtils.getMimeType(view.getContext(), encodePath);

        //enterplorer协议判断
        if (url.startsWith("enterplorer://")) {
            if (mDeveloperAppModel != null) {
                String proxyServer = mDeveloperAppModel.getAppPath();
                String resPath = proxyServer.substring(0, proxyServer.length() - 2) + encodePath;
                InputStream is = loadProxyStream(resPath);
                if (is != null) {
                    return super.createXWalkWebResourceResponse(type, ENCODING, is);
                }
            } else {
                String path = uri.getHost() + encodePath;
                String targetSrc = view.getContext().getFilesDir().getPath() + File.separator + ContentValues.APP_WEB_ROOT_PATH + File.separator + ContentValues.YSP_NEW_ADAPTER_PAC_PATH + File.separator + path;
                try {
                    InputStream is = new FileInputStream(targetSrc);
                    return super.createXWalkWebResourceResponse(type, ENCODING, is);
                } catch (FileNotFoundException ignored) {
                }
            }
        }

        //======XCloud1=====
        if (mMatcherResult != null && encodePath.endsWith("ysp_head_init.js")) {
            try {
                String runtimeEncodeRoot = getRuntimeVersion(mMatcherResult.getCloudAppModle());
                String fileName = view.getContext().getFilesDir().getPath() + File.separator + runtimeEncodeRoot + File.separator + "_init.js";
                InputStream is = new FileInputStream(fileName);
                return super.createXWalkWebResourceResponse(type, ENCODING, is);
            } catch (Exception ignored) {
            }
        }

        if (encodePath.endsWith("ysp_head_init.js")) {
            try {
                String aes1 = FileUtils.readAssertResource(view.getContext(), "_init.js");
                String aes2 = getInjectContent(view.getContext(), mHomeURL);
                InputStream is = new ByteArrayInputStream((aes1 + aes2).getBytes());
                return super.createXWalkWebResourceResponse(type, ENCODING, is);
            } catch (Exception ignored) {
            }
        }

        if (encodePath.endsWith("ysp_init.js") || encodePath.endsWith("ysp_body_init.js")) {
            try {
                InputStream is = view.getContext().getAssets().open("empty");
                return super.createXWalkWebResourceResponse(type, ENCODING, is);
            } catch (Exception ignored) {
            }
        }

        //======XCloud2======
        if (mMatcherResult != null) {
            //资源重载（只重载当前适配包里面的资源）
            String targetOverrideFileName = getOverrideTargetUrl(mMatcherResult.getCloudAppModle(), url);
            if (!TextUtils.isEmpty(targetOverrideFileName)) {
                DeveloperAppModel developerAppModel = mMatcherResult.getDeveloperAppModel();
                if (developerAppModel != null) {
                    String proxyServer = developerAppModel.getAppPath();
                    String resPath = proxyServer + targetOverrideFileName.replace(mMatcherResult.getCloudAppModle().getScope() + File.separator, "");
                    InputStream is = loadProxyStream(resPath);
                    if (is != null) {
                        return super.createXWalkWebResourceResponse(type, ENCODING, is);
                    }
                } else {
                    String fileName = view.getContext().getFilesDir().getPath() + File.separator + ContentValues.APP_WEB_ROOT_PATH + File.separator + ContentValues.YSP_NEW_ADAPTER_PAC_PATH + File.separator + targetOverrideFileName;
                    try {
                        InputStream is = new FileInputStream(fileName);
                        return super.createXWalkWebResourceResponse(type, ENCODING, is);
                    } catch (Exception ignored) {
                    }
                }
            }

            String runtimePath = getRuntimeVersion(mMatcherResult.getCloudAppModle());
            //适配包的资源替换
            if (encodePath.startsWith(File.separator + runtimePath + File.separator + ContentValues.YSP_NEW_ADAPTER_PAC_PATH)) {
                DeveloperAppModel developerAppModel = mMatcherResult.getDeveloperAppModel();
                if (developerAppModel != null) {
                    String proxyServer = developerAppModel.getAppPath();
                    String str = encodePath.substring(encodePath.indexOf("xcloud2json/") + 12);
                    String server = proxyServer + str.replace(mMatcherResult.getCloudAppModle().getScope() + File.separator, "");
                    InputStream is = loadProxyStream(server);
                    if (is != null) {
                        return super.createXWalkWebResourceResponse(type, ENCODING, is);
                    }
                } else {
                    try {
                        String fileName = view.getContext().getFilesDir().getPath() + File.separator + ContentValues.APP_WEB_ROOT_PATH + File.separator + ContentValues.YSP_NEW_ADAPTER_PAC_PATH + File.separator + encodePath.substring(encodePath.indexOf("xcloud2json/") + 12);
                        InputStream is = new FileInputStream(fileName);
                        return super.createXWalkWebResourceResponse(type, ENCODING, is);
                    } catch (Exception ignored) {
                    }
                }
            }

            //运行时资源替换
            if (encodePath.startsWith(File.separator + runtimePath)) {
                try {
                    String fileName = view.getContext().getFilesDir().getPath() + encodePath;
                    InputStream is = new FileInputStream(fileName);
                    return super.createXWalkWebResourceResponse(type, ENCODING, is);
                } catch (Exception ignored) {
                }
            }

            //无用资源过滤,如果是双WebView，则自动过滤所有图片资源
            if (!TextUtils.isEmpty(type)) {
                XCloudAppModel xCloudAppModel = mMatcherResult.getCloudAppModle();
                if (shouldFilterResource(xCloudAppModel, url, type)) {
                    try {
                        InputStream is = view.getContext().getAssets().open("empty");
                        return super.createXWalkWebResourceResponse(type, ENCODING, is);
                    } catch (Exception ignored) {
                    }
                }
            }
        }
        return null;
    }

    //获取需要注入init.js的资源内容
    private String getInjectContent(Context context, String tabUrl) {
        boolean fromProxy = false;
        List<XCloudAppModel> xCloudAppModels = xCloud2Map.getXCloudAppModels();
        if (mMatcherResult != null) {
            DeveloperAppModel developerAppModel = mMatcherResult.getDeveloperAppModel();
            if (developerAppModel != null) {
                fromProxy = true;
                xCloudAppModels.clear();
                xCloudAppModels.add(mMatcherResult.getCloudAppModle());
            }
        }
        String content = "";
        for (XCloudAppModel xCloudAppModel : xCloudAppModels) {
            if (tabUrl.equals(xCloudAppModel.getStartURL())) {
                List<InjectModel> injectModels = xCloudAppModel.getInjectModels();
                for (InjectModel injectModel : injectModels) {
                    String path = injectModel.getPath();
                    String filePath = "";
                    if (path.startsWith("enterplorer://")) {
                        filePath = context.getFilesDir().getPath() + File.separator + ContentValues.APP_WEB_ROOT_PATH + File.separator + ContentValues.YSP_NEW_ADAPTER_PAC_PATH + File.separator + path.replace("enterplorer://", "");
                    } else {
                        filePath = context.getFilesDir().getPath() + File.separator + ContentValues.APP_WEB_ROOT_PATH + File.separator + ContentValues.YSP_NEW_ADAPTER_PAC_PATH + File.separator + xCloudAppModel.getScope() + File.separator + path;
                    }
                    if (!fromProxy) {
                        content += FileUtils.readFile(filePath);
                    } else {
                        //TODO:通过代理服务器从studio中取资源
                        String resPath = "";
                        String proxyServer = mMatcherResult.getDeveloperAppModel().getAppPath();
                        if (path.startsWith("enterplorer://")) {
                            resPath = proxyServer.substring(0, proxyServer.length() - 2) + Uri.parse(path).getEncodedPath();
                        } else {
                            resPath = proxyServer + path;
                        }
                        content += loadProxyData(resPath);
                    }
                }
                break;
            }
        }
        return content;
    }

    //获取资源重载的目标资源文件
    private String getOverrideTargetUrl(XCloudAppModel xCloudAppModel, String url) {
        List<OverrideRegexModel> listModule = xCloudAppModel.getOverrideModuleList();
        for (OverrideRegexModel module : listModule) {
            List<String> matcherList = module.getMatcherList();
            for (String res : matcherList) {
                try {
                    if (url.matches(res)) {
                        return xCloudAppModel.getScope() + File.separator + module.getTargetURL();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return "";
    }

    //是否过滤适配的某个资源
    private boolean shouldFilterResource(XCloudAppModel xCloudAppModel, String url, String type) {
        InterceptModel interceptModel = xCloudAppModel.getInterceptModel();
        if (interceptModel != null) {
            List<String> ignoreResList = interceptModel.getIgnoreResMatcherList();
            for (String matcher : ignoreResList) {
                try {
                    if (url.matches(matcher)) {
                        return false;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            List<String> typeList = interceptModel.getTypes();
            for (String givType : typeList) {
                if (type.contains(givType)) {
                    return true;
                }
            }
        }
        return false;
    }

    //获取运行时的具体信息
    private String getRuntimeVersion(XCloudAppModel xCloudAppModel) {
        String version = "";
        String runtimeVersion = xCloudAppModel.getRuntimeVersion();
        if (!TextUtils.isEmpty(runtimeVersion)) {
            if (runtimeVersion.startsWith("^")) {
                runtimeVersion = runtimeVersion.replace("^", "");
                version = runtimeVersion.split("\\.")[0] + ".+";
            } else {
                version = runtimeVersion;
            }
        }
        return ContentValues.APP_ENGINE_ROOT_PATH + File.separator + version;
    }

    //将本地资源替换指向代理服务器
    private InputStream loadProxyStream(String url) {
        OkHttpClient client = EnterClient.getInstances().getManagerClient();
        Request proxyRequest = new Request.Builder().url(url).build();
        try {
            Response response = client.newCall(proxyRequest).execute();
            if (response.code() == 200) {
                return response.body().byteStream();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private String loadProxyData(String url) {
        OkHttpClient client = EnterClient.getInstances().getManagerClient();
        Request proxyRequest = new Request.Builder().url(url).build();
        try {
            Response response = client.newCall(proxyRequest).execute();
            if (response.code() == 200) {
                return response.body().string();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void setDeveloperAppModel(DeveloperAppModel mDeveloperAppModel) {
        this.mDeveloperAppModel = mDeveloperAppModel;
    }

    @Override
    public void onLoadStarted(XWalkView view, String url) {
        super.onLoadStarted(view, url);
        if (mMatcherResult != null) {
            String runtimePath = getRuntimeVersion(mMatcherResult.getCloudAppModle());
            if (url.contains(runtimePath)) {
                startLocalResLog(url);
            } else {
                startNetResLog(url);
            }
        }
    }

    private Map<String, String> resLengthMap = new HashMap<>();

    @Override
    public void onReceivedResponseHeaders(XWalkView view, XWalkWebResourceRequest request, XWalkWebResourceResponse response) {
        super.onReceivedResponseHeaders(view, request, response);
        if (mMatcherResult != null) {
            Map<String, String> headers = response.getResponseHeaders();
            if (headers.containsKey("Content-Length")) {
                String url = request.getUrl().toString();
                String length = headers.get("Content-Length");
                resLengthMap.put(url, length);
            }
        }
    }

    @Override
    public void onReceivedResponse(XWalkView view, String url) {
        super.onReceivedResponse(view, url);
        Log.i("_onReceivedResponse", url);
        if (url.contains("runtimeEngineWithApp.html")) {
            YspLogUtils.d("heart beat : check");
            xCloud2Map.doCheck();
        }
        if (mMatcherResult != null) {
            String length = "0";
            if (resLengthMap.containsKey(url)) {
                length = resLengthMap.get(url);
                resLengthMap.remove(url);
            }
            String runtimePath = getRuntimeVersion(mMatcherResult.getCloudAppModle());
            if (url.contains(runtimePath)) {
                endLocalResLog(url, length);
            } else {
                endNetResLog(url, length);
            }
        }
    }

    private void startLocalResLog(String url) {
        if (mMatcherResult != null) {
            XCloudAppModel xCloudAppModel = mMatcherResult.getCloudAppModle();
            YspLogUtils.localResStart(url, xCloudAppModel.getScope(), xCloudAppModel.getRuntimeVersion());
        }
    }

    private void endLocalResLog(String url, String length) {
        if (mMatcherResult != null) {
            XCloudAppModel xCloudAppModel = mMatcherResult.getCloudAppModle();
            YspLogUtils.localResEnd(url, xCloudAppModel.getScope(), xCloudAppModel.getRuntimeVersion(), length);
        }
    }

    private void startNetResLog(String url) {
        if (mMatcherResult != null) {
            XCloudAppModel xCloudAppModel = mMatcherResult.getCloudAppModle();
            YspLogUtils.netResStart(url, xCloudAppModel.getScope(), xCloudAppModel.getRuntimeVersion());
        }
    }

    private void endNetResLog(String url, String length) {
        if (mMatcherResult != null) {
            XCloudAppModel xCloudAppModel = mMatcherResult.getCloudAppModle();
            YspLogUtils.netResEnd(url, xCloudAppModel.getScope(), xCloudAppModel.getRuntimeVersion(), length);
        }
    }

    @Override
    public void onLoadFinished(XWalkView view, String url) {
        super.onLoadFinished(view, url);
        String currentUrl = view.getUrl();
        if (!TextUtils.isEmpty(currentUrl) && mMatcherResult == null) {
            view.loadUrl("javascript: autoYSPlogin();");
        }
    }
}

